#include "parser-tools.h"
//necessary
#include "NodeType.h"
#include <stdlib.h>


int parserToolsComputeSyntaxNode(FILE* f,PSyntaxNode node,int nodenumber);

int parserToolComputeSyntaxNode2(FILE* f,PSyntaxNode pnode,int nodenumber,int childnumber);

bool buildSyntaxTreeGraph(const char* filename,PSyntaxNode root,bool jpgimage,bool removedotfile){
	char buffer[__PARSER_TOOLS_MAX_FILENAME_LENGTH];
	sprintf(buffer,"grp/%s.dot",filename);
	FILE* f=fopen(buffer,"w");
	if (f==NULL){
		fprintf(stderr,"parser-tools.c:buildSyntaxTreeGraph:can't create file grp/%s.dot!\n",filename);
		return false;
	}
	fprintf(f,"digraph %s {\n",filename);
	parserToolComputeSyntaxNode2(f,root,0,1);
	//parserToolsComputeSyntaxNode(f,root,0);
	fprintf(f,"}");
	fflush(f);
	fclose(f);
	if (jpgimage==true){
		char command[3*__PARSER_TOOLS_MAX_FILENAME_LENGTH];
		sprintf(command,"dot -Tjpg grp/%s.dot -o grp/%s.jpg",filename,filename);
		int result=system(command);
		if (result!=0){
			fprintf(stderr,"parser-tools.c:buidlSyntaxTreeGraph:can't create jpg image %s.jpg!\n",filename);
			return false;
		}
	}
	if (removedotfile==true){
		char command[10+__PARSER_TOOLS_MAX_FILENAME_LENGTH];
		sprintf(command,"rm grp/%s.dot",filename);
		int result=system(command);
		if (result!=0){
			fprintf(stderr,"parser-tools.c:buildSyntaxTreeGraph:can't remove %s.dot!\n",filename);
			return false;
		}
	}
	return true;
}
/**The output of this function should be this structure:
 * 	\li every 2 node which are brothers has to have the same rank;
 * 	\li the parent has a greater rank than the child;
 * 	\li child relationship is marked by a red arrow;
 * 	\li brother relationship is marked by a blue arrow;
 *
 * The recursive mechanism works:
 * 	\li node brothers are computated first;
 * 	\li child are computated secondly;
 * 	\li node are computated horizontally;
 *
 * @param f the file to write on the dot expression;
 * @param pnode the node to be write
 * @param nodenumber the identifier of the node. Every node must have a different identifier;
 * @param childnumber indicates an additional number that represents the child number. If a parent has 5 childs node, the first one (pnode->child)
 * 	has the number 1, while pnode->child->brother has the number 2 and so on.
 * @return the numebr of node which are (directly or indirectly) children of pnode
 */
int parserToolComputeSyntaxNode2(FILE* f,PSyntaxNode pnode,int nodenumber,int childnumber){
	int childNodeUsed=0;
	int brotherNodeUsed=0;
	int lexvalmeaning;
	if (pnode->brother!=NULL && childnumber==1){
		//the node has at least a brother; since every brother has the same dot.rank a subgraph needs to be created
		//this node is the first child. So we need to write the "open subgraph" token
		fprintf(f,"{\n");
		fprintf(f,"rank=same;\n");
	}
	//---------- NODE CREATION -------------
	fprintf(f,"n%02d",nodenumber);
	fprintf(f,"[label=\"");
	printNodeType(f,pnode->type,"\\n");
	lexvalmeaning=getSyntaxNodeValueMeaning(pnode);
	if (lexvalmeaning!=LEXVAL_NIHIL_MEANING){
		fprintf(f,"\\n");
		printLexVal(f,pnode->value,lexvalmeaning);
		fprintf(f,"\" style=\"filled\" fillcolor=\"yellow\"");
	}else{
		fprintf(f,"\"");
	}
	fprintf(f,"];\n");
	//--------------END NODE CREATION ------------------
	if (pnode->brother!=NULL){
		fprintf(f,"n%02d -> n%02d [color=blue];\n",nodenumber,nodenumber+1);
		brotherNodeUsed=parserToolComputeSyntaxNode2(f,pnode->brother,nodenumber+1,childnumber+1);
	}
	if (pnode->brother==NULL && childnumber!=1){//this node has no further brother; however it is the last children a unknown parent has. So we have to close the subgraph
		fprintf(f,"}\n");
	}
	if (pnode->child!=NULL){
		fprintf(f,"n%02d -> n%02d [color=red];\n",nodenumber,nodenumber+brotherNodeUsed+1);
		childNodeUsed=parserToolComputeSyntaxNode2(f,pnode->child,nodenumber+brotherNodeUsed+1,1);//pnode->child is the first child, so the brothernumebr is set to 1
	}
	return childNodeUsed+brotherNodeUsed+1;
}

//TODO deprecated function. This function cannot support sub graph of dot 'cause the recursive method used is depth-first
int parserToolsComputeSyntaxNode(FILE* f,PSyntaxNode node,int nodenumber){
	int childNodeUsed,brotherNodeUsed;
	fprintf(f,"n%02d",nodenumber);
	fprintf(f,"[label=\"");
	printNodeType(f,node->type,"\\n");
	switch (getSyntaxNodeValueMeaning(node)){
	case LEXVAL_INTEGER_MEANING: {
		fprintf(f,"\\n%d\" ",node->value.ival);
		fprintf(f,"style=bold");
		break;
	}
	case LEXVAL_STRING_MEANING: {
		fprintf(f,"\\n%s\" ",node->value.sval);
		fprintf(f," style=bold");
		break;
	}
	case LEXVAL_NIHIL_MEANING: {
		fprintf(f,"\"");
		break;
	}
	}
	fprintf(f,"];\n");
	if (node->child!=NULL){
		fprintf(f,"n%02d",nodenumber);
		fprintf(f," -> ");
		fprintf(f,"n%02d",nodenumber+1);
		fprintf(f," [color=red];\n");
		childNodeUsed=parserToolsComputeSyntaxNode(f,node->child,nodenumber+1);
	}
	if (node->brother!=NULL){
		fprintf(f,"n%02d",nodenumber);
		fprintf(f," -> ");
		fprintf(f,"n%02d",nodenumber+1+childNodeUsed);
		fprintf(f," [color=blue];\n");
		brotherNodeUsed=parserToolsComputeSyntaxNode(f,node->brother,nodenumber+1+childNodeUsed);
	}
	return childNodeUsed+brotherNodeUsed;
}

